import random
from itertools import permutations

from app.core.handlers.response import SuccessResponse


def card_to_number(card: str):
    card_split = [card[0], card[1:]]
    numbered_split = [
        card_suit_to_number(card_split[0]),
        card_rank_to_number(card_split[1]),
    ]

    return numbered_split[0] + (numbered_split[1] - 1) * 4 + 1


def card_rank_to_number(card_rank: str) -> int:
    if card_rank == "J":
        return 11
    if card_rank == "Q":
        return 12
    if card_rank == "K":
        return 13
    if card_rank == "A":
        return 1
    return int(card_rank)


def card_suit_to_number(card_suit: str) -> int:
    if card_suit == "♠":
        return 3
    if card_suit == "♥":
        return 2
    if card_suit == "♣":
        return 1
    return 0


def number_to_card_rank(number: int) -> str:
    if number == 11:
        return "J"
    if number == 12:
        return "Q"
    if number == 13:
        return "K"
    if number == 1:
        return "A"
    return str(number)


def number_to_card_suit(number: int) -> str:
    if number == 3:
        return "♠"
    if number == 2:
        return "♥"
    if number == 1:
        return "♣"
    return "♦"


def number_to_card(number: int) -> str:
    # 从1开始的编号转回花色和点数
    adjusted_number = number - 1  # 调整为从0开始
    suit_number = adjusted_number % 4  # 花色编号
    rank_number = adjusted_number // 4 + 1  # 点数编号

    return number_to_card_suit(suit_number) + number_to_card_rank(rank_number)


def generate_random_cards():
    """
    从1-52生成5个不同数字
    每个数字代表一张唯一的扑克牌（1-52对应52张牌）
    """
    # 使用random.sample确保不重复
    card_numbers = random.sample(range(1, 53), 5)
    return card_numbers


def generate_random_cards_string() -> str:
    """
    生成5张随机扑克牌的字符串表示
    """
    card_numbers = generate_random_cards()
    card_strings = [number_to_card(num) for num in card_numbers]
    return ",".join(card_strings)


def card_guess_sort_easy(cards: str):
    card_list = cards.split(",")

    # 找出两张花色一致的牌,赋值给this,that
    suit_map: dict = {}
    for card in card_list:
        suit = card[0]
        if suit not in suit_map:
            suit_map[suit] = []
        suit_map[suit].append(card)

    this, that = None, None

    # 找到花色一致的两张牌
    for cards_in_suit in suit_map.values():
        if len(cards_in_suit) >= 2:
            this = cards_in_suit[0]
            that = cards_in_suit[1]
            break

    if this is None or that is None:
        raise ValueError("无法找到两张花色一致的牌")

    this_rand_number = card_rank_to_number(this[1:])
    that_rand_number = card_rank_to_number(that[1:])

    # 计算点数差值
    diff = this_rand_number - that_rand_number

    # 根据规则确定隐藏的牌和第一张牌
    # 规则：如果差值≤6，隐藏点数大的；否则隐藏点数小的
    if (abs(diff) <= 6 and diff > 0) or (abs(diff) > 6 and diff < 0):
        selected_card = this  # 隐藏this
        first_card = that  # first_card是that
    else:
        selected_card = that  # 隐藏that
        first_card = this  # first_card是this

    # 剩余3张牌, 按小中大,小大中....生成6种排序
    # 获取并排序剩余的牌
    remaining_cards = [card for card in card_list if card not in [this, that]]

    # 按点数排序剩余的牌
    remaining_cards.sort(key=lambda x: card_rank_to_number(x[1:]))

    # 生成6种排列组合
    arrangements = list(permutations(remaining_cards))

    # 根据差值的绝对值确定使用哪种排列
    abs_diff = abs(diff)
    arrangement_index = (abs_diff - 1) % 6  # 确保索引在0-5范围内

    # 选择对应的排列
    ordered_cards = list(arrangements[arrangement_index])

    # 构造最终结果：第一张牌 + 排序后的剩余3张牌
    result = {
        "selected_card": selected_card,
        "ordered_card": ",".join([first_card] + ordered_cards),
    }

    return result


def card_guess_generate_easy():
    """
    生成5张随机扑克牌的字符串表示
    """
    cards_string = generate_random_cards_string()
    result = card_guess_sort_easy(cards_string)

    return SuccessResponse(data={"ordered_card": result.get("ordered_card")})


def card_guess_solve_easy(cards: str):
    card_split = cards.split(",")
    first_card = card_split[0]
    suit = first_card[0]
    rank_number = card_rank_to_number(first_card[1:])

    # 获取剩余3张牌
    remaining_cards = card_split[1:]
    # 转换为数字, 排序
    remaining_numbers = sorted([card_to_number(card) for card in remaining_cards])

    # 生成所有排列并直接查找索引
    arrangements_numbers = list(permutations(remaining_numbers))
    arrangements = [
        tuple(number_to_card(number) for number in number_list)
        for number_list in arrangements_numbers
    ]
    # 查找当前排列的索引
    try:
        arrangement_index = arrangements.index(tuple(remaining_cards))
    except ValueError:
        raise ValueError("无法找到匹配的排列")

    new_rank_number = rank_number + arrangement_index + 1
    if new_rank_number > 13:
        new_rank_number -= 13

    rank = number_to_card_rank(new_rank_number)

    return SuccessResponse(data=f"{suit}{rank}")


def card_guess_check_easy(cards: str, answer: str):
    result = card_guess_solve_easy(cards)
    if (data := result["data"]) == answer:
        return SuccessResponse(message="恭喜你，推理正确！", data=data)
    else:
        return SuccessResponse(
            message=f"推理错误，请重新尝试！, 正确答案为:{data}",
            data=data,
        )


def card_guess_sort_hard(cards: str):
    card_list = cards.split(",")
    card_num_list = [card_to_number(card) for card in card_list]
    card_num_list.sort()

    # 求和并求余
    index = sum(card_num_list) % 5 - 1
    if index < 0:
        index += 5

    select_num = card_num_list.pop(index)
    select_card = number_to_card(select_num)

    # 所有数字每5个为一组, 算出selected_card 是第几组
    group = (select_num - 1) // 5

    arrangements_numbers = list(permutations(card_num_list))

    ordered_num = arrangements_numbers[group]
    ordered_cards = [number_to_card(num) for num in ordered_num]

    return {
        "selected_card": select_card,
        "ordered_card": ",".join(ordered_cards),
    }


def card_guess_generate_hard():
    """
    生成5张随机扑克牌的字符串表示(困难模式)
    """
    cards_string = generate_random_cards_string()
    result = card_guess_sort_hard(cards_string)

    return SuccessResponse(data={"ordered_card": result.get("ordered_card")})


def card_guess_solve_hard(cards: str):
    card_split = cards.split(",")
    card_numbers = [card_to_number(card) for card in card_split]
    card_number_sort = sorted(card_numbers)

    arrangements_numbers = list(permutations(card_number_sort))

    group = arrangements_numbers.index(tuple(card_numbers))

    number_available = list(range(group * 5 + 1, group * 5 + 6))
    _result = 1
    for number_pick in number_available:
        new_numbers = [number_pick] + card_number_sort[:]
        new_numbers.sort()
        mod_pick = new_numbers.index(number_pick) + 1
        if mod_pick == 5:
            mod_pick = 0
        mod = sum(new_numbers) % 5
        if mod == mod_pick:
            _result = number_pick
    return SuccessResponse(data=number_to_card(_result))


def card_guess_check_hard(cards: str, answer: str):
    result = card_guess_solve_hard(cards)
    if (data := result["data"]) == answer:
        return SuccessResponse(message="恭喜你，推理正确！", data=data)
    else:
        return SuccessResponse(
            message=f"推理错误，请重新尝试！, 正确答案为:{data}",
            data=data,
        )


if __name__ == "__main__":
    cards_string = generate_random_cards_string()
    result = card_guess_sort_hard(cards_string)
    print(result)
    ordered_card = result.get("ordered_card")
    print(card_guess_solve_hard(ordered_card))
